#include "StdAfx.h"
#include "FilerFrogUtils.h"
#include <shellapi.h>
#include "..\FilesRefactor\FileMachine.h"
#include "..\FilesRefactor\FileMachine.h"
#include <cctype>
#include <algorithm>

bool FilerFrogUtils::IsVistaOs()
{
	bool isVistaOs = false;

	OSVERSIONINFOEX inf;
	SecureZeroMemory(&inf, sizeof(OSVERSIONINFOEX));
	inf.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
	GetVersionEx((OSVERSIONINFO *)&inf);

	isVistaOs = (inf.dwMajorVersion >= 6);

	return isVistaOs;
}

wstring FilerFrogUtils::GetFileDirectoyPath(const wstring& filePath)
{
	wstring retVal = L"";

	int pos = filePath.length() - 1;

	if (filePath.length() > 0)
	{
		while (pos >= 0 && filePath.at(pos) == L'\\')
		{
			pos--;
		}

		for (int i = (int)pos; i > 0 ; i--)
		{
			if (filePath.at(i) == L':')
			{
				retVal = filePath.substr(0, i + 1);
				break;
			}
			else if (filePath.at(i) == L'\\')
			{
				retVal = filePath.substr(0, i);
				break;
			}
		}
	}

	return retVal;
}

wstring FilerFrogUtils::GetSeceretFilePath()
{
	wstring retVal = L"";
	retVal = GetFrogAppDataPath() + L"FilerFrog.sw2";
	return retVal;
}

wstring FilerFrogUtils::GetFileNameFromPath(const wstring& filePath)
{
	wstring retVal = filePath;

	if (filePath.length() > 0)
	{
		int pos = filePath.length() - 1;

		while (pos >= 0 && filePath.at(pos) != L'\\')
		{
			pos--;
		}

		if (pos +1 < filePath.length())
		{
			retVal = filePath.substr(pos + 1);
		}
	}

	return retVal;
}

void FilerFrogUtils::MakeListInDir(const wstring& dir, list<wstring>& retVal)
{
	WIN32_FIND_DATA ffd;
	HANDLE hFind = INVALID_HANDLE_VALUE;
	DWORD dwError=0;

	wstring findIn(dir + L"\\*");
	hFind = FindFirstFile(findIn.c_str(), &ffd);

	if (INVALID_HANDLE_VALUE == hFind) 
	{
		wcout << L"MakeListInDir: Error trying FindFirstFile" << endl;
		return;
	}

	FindNextFile(hFind, &ffd);
	while (FindNextFile(hFind, &ffd) != 0)
	{
		wstring tmp(dir + L"\\" + ffd.cFileName);
		retVal.push_back(tmp);
	}

	dwError = GetLastError();
	if (dwError != ERROR_NO_MORE_FILES) 
	{
		wcout << L"Unexpected Error." << endl;
		return;
	}

	FindClose(hFind);
}

wstring FilerFrogUtils::GetFileNameWithoutExtension(const wstring& filePath)
{
	wstring retVal = filePath;

	int pos = retVal.length() - 1;

	while (pos > 0 && retVal.at(pos) != L'.')
	{
		pos--;
	}

	if (pos > 0)
	{
		retVal = retVal.substr(0, pos);
	}

	return retVal;
}

wstring FilerFrogUtils::GetFileNameExtension(const wstring& filePath)
{
	wstring retVal = filePath;

	int pos = retVal.length() - 1;

	while (pos > 0 && retVal.at(pos) != L'.')
	{
		pos--;
	}

	if (pos > 0)
	{
		retVal = retVal.substr(pos + 1, retVal.length() - pos -1);
	}

	return retVal;
}

wstring FilerFrogUtils::GetFrogAppDataPath()
{
	wstring retVal = L"";
	wchar_t appDataFolder[MAX_PATH] = L"";
	SHGetSpecialFolderPath(NULL, appDataFolder, CSIDL_COMMON_APPDATA, TRUE);
	retVal = wstring(appDataFolder) + L"\\FilerFrog\\";
	SHCreateDirectory(NULL, retVal.c_str());
	return retVal;
}

bool FilerFrogUtils::CopyStringToClipboard(const wstring& str)
{
	// MessageBox(NULL, str.c_str(), str.c_str(), 0);

	HGLOBAL hglbCopy;
	wchar_t* lptstrCopy;

	if (!OpenClipboard(NULL))
	{
		return false;
	}

	EmptyClipboard(); 

	size_t length = str.length();
	hglbCopy = GlobalAlloc(GMEM_MOVEABLE, (length + 1) * sizeof(wchar_t)); 

	// Lock the handle and copy the text to the buffer. 
	lptstrCopy = (wchar_t*)GlobalLock(hglbCopy); 

	memcpy(lptstrCopy, str.c_str(), length * sizeof(wchar_t)); 

	// null character 
	lptstrCopy[length] = (wchar_t)0;

	GlobalUnlock(hglbCopy); 

	// Place the handle on the clipboard. 
	SetClipboardData(CF_UNICODETEXT, hglbCopy); 

	// Close the clipboard. 
	CloseClipboard(); 

	return true;
}

void FilerFrogUtils::SwapItems(HWND hWndList,int nSourceIndex,int nDestIndex)
{
	//now swap the items	
	wchar_t szSourceText[256], szDestText[256];

	//get source
	LVITEM lvSItem;
	lvSItem.iSubItem = 0;
	lvSItem.cchTextMax = 256;
	lvSItem.iItem = nSourceIndex;
	lvSItem.pszText = szSourceText;

	lvSItem.mask = (LVIF_PARAM | LVIF_TEXT | LVIF_IMAGE | LVIF_STATE);
	ListView_GetItem(hWndList,&lvSItem);

	//get dest
	LVITEM lvDItem;
	lvDItem.iSubItem = 0;
	lvDItem.iItem = nDestIndex;
	lvDItem.cchTextMax = 256;
	lvDItem.pszText = szDestText;
	lvDItem.mask = (LVIF_PARAM | LVIF_TEXT | LVIF_IMAGE | LVIF_STATE);
	ListView_GetItem(hWndList,&lvDItem);

	//now swap
	lvSItem.iItem = nDestIndex;
	lvDItem.iItem = nSourceIndex;

	// Set as selected and focused
	lvSItem.state = LVIS_SELECTED | LVIS_FOCUSED;
	lvSItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;

	// Clear selction and focues for this item
	lvDItem.state = 0;
	lvDItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;

	ListView_SetItem(hWndList,&lvSItem);
	ListView_SetItem(hWndList,&lvDItem);
}

HICON FilerFrogUtils::GetExtensionSmallIcon(const wstring& fileExt)
{
	HICON retVal = NULL;

	SHFILEINFO sfi;
	ZeroMemory(&sfi, sizeof(sfi));

	FileMachine fileMachine(NULL, fileExt);

	if (fileMachine.IsFile())
	{
		SHGetFileInfo(fileExt.c_str(), FILE_ATTRIBUTE_NORMAL, &sfi, sizeof(SHFILEINFO), SHGFI_USEFILEATTRIBUTES | SHGFI_ICON | SHGFI_SMALLICON);
	}
	else
	{
		SHGetFileInfo(fileExt.c_str(), FILE_ATTRIBUTE_DIRECTORY, &sfi, sizeof(SHFILEINFO), SHGFI_USEFILEATTRIBUTES | SHGFI_ICON | SHGFI_SMALLICON);
	}

	return sfi.hIcon; 
}


void FilerFrogUtils::SetTopMost(HWND hWnd, const BOOL TopMost)   
{   
	HWND hWndInsertAfter = (TopMost ? HWND_TOPMOST : HWND_NOTOPMOST);   
	SetWindowPos(hWnd, hWndInsertAfter, 0, 0 , 0 , 0, SWP_NOMOVE | SWP_NOSIZE);   
}

bool FilerFrogUtils::IsDirectory(const wstring& filePath)
{
	FileMachine fileMachine(NULL, filePath);
	return !fileMachine.IsFile();
}

bool FilerFrogUtils::IsDirectoryInRoot(const wstring& filePath)
{
	wstring path = filePath + L"\\";

	int slashCount = 0;

	for (int i=0; i<path.size(); i++)
	{
		if (path.at(i) == L'\\')
		{
			slashCount++;
		}

		while (i<path.size() && path.at(i) == L'\\')
		{
			i++;
		}

		if (slashCount > 1)
		{
			return false;
		}
	}

	return true;
}

bool FilerFrogUtils::IsCharInInvalidFileNameChar(wchar_t c)
{
	for (int i=0; i<INVALID_FILENAME_CHAR_CONUT; i++)
	{
		if (invalidFileNameChars[i] == c)
		{
			return true;
		}
	}

	return false;
}

bool FilerFrogUtils::IsFileNameValid(const wstring& fileName)
{
	if (fileName == L"")
	{
		return false;
	}

	else
	{
		if (fileName.at(0) == L' ')
		{
			return false;
		}

		for (int i=0; i<fileName.length(); i++)
		{
			if (IsCharInInvalidFileNameChar(fileName.at(i)))
			{
				return false;
			}
		}
	}

	// All chars ok
	return true;
}


wstring FilerFrogUtils::ToLower(const wstring& str)
{
	wstring retVal = str;
	std::transform(retVal.begin(), retVal.end(), retVal.begin(), (int(*)(int)) tolower);
	return retVal;
}

int FilerFrogUtils::GetPassedDays(time_t startDate, time_t endDate)
{
	int retVal = 0;

	double seconds = difftime(endDate, startDate);

	retVal = (int)(seconds / (24 * 60 * 60));

	return retVal;
}

int FilerFrogUtils::GetPassedDaysFromToday(time_t startDate)
{
	time_t today;
	time(&today);
	return GetPassedDays(startDate, today);
}

time_t FilerFrogUtils::GetLastSavedDate()
{
	time_t retVal = 0;

	CRegKey key;

	long nError = key.Open(HKEY_CURRENT_USER, L"Software\\FilerFrog", KEY_READ);

	if (nError == ERROR_SUCCESS)
	{
		ULONG nBytes = sizeof(time_t);
		key.QueryBinaryValue(L"LastCheckedForUpdates", &retVal, &nBytes);

		if (nBytes != sizeof(time_t))
		{
			retVal = 0;
		}
	}

	return retVal;
}

void FilerFrogUtils::SetTodayAsLastSavedDate()
{
	time_t today;
	time(&today);

	CRegKey key;

	long nError = key.Open(HKEY_CURRENT_USER, L"Software\\FilerFrog", KEY_WRITE);

	if (nError == ERROR_SUCCESS)
	{
		ULONG nBytes = sizeof(time_t);
		key.SetBinaryValue(L"LastCheckedForUpdates", &today, nBytes);
	}
}

int FilerFrogUtils::GetPassedDaysFromLastSavedDay()
{
	time_t lastSavedDate = GetLastSavedDate();
	return GetPassedDaysFromToday(lastSavedDate);
}


wstring FilerFrogUtils::GetDesktopDirectory()
{
	wchar_t strPath[MAX_PATH];
	wstring desktopPath = L"";

	if (SHGetSpecialFolderPath(0, strPath, CSIDL_DESKTOPDIRECTORY, FALSE))
	{
		desktopPath = strPath;
	}

	return desktopPath;
}

wstring FilerFrogUtils::GetDesktopAllDirectory()
{
	wchar_t strPath[MAX_PATH];
	wstring desktopPath = L"";

	if (SHGetSpecialFolderPath(0, strPath, CSIDL_COMMON_DESKTOPDIRECTORY, FALSE))
	{
		desktopPath = strPath;
	}

	return desktopPath;
}
